﻿using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;

namespace WinwiseARDrone.TabletClient.Controls
{
    /// <summary>
    /// Contrôle de sélection en demi-lune
    /// </summary>
    public partial class HalfMoonSelector : Control
    {
        #region Routed Events

        public static readonly RoutedEvent LeftSelectedEvent = EventManager.RegisterRoutedEvent("LeftSelected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(HalfMoonSelector));
        public static readonly RoutedEvent RightSelectedEvent = EventManager.RegisterRoutedEvent("RightSelected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(HalfMoonSelector));

        #endregion

        #region Propriétés de dépendance

        public static readonly DependencyProperty IsRigthSelectedProperty = DependencyProperty.Register("IsRigthSelected", typeof(bool), typeof(HalfMoonSelector), new UIPropertyMetadata(true, new PropertyChangedCallback(HalfMoonSelector.OnIsRigthSelectedChanged)));
        public static readonly DependencyProperty CommandLeftSelectProperty = DependencyProperty.Register("CommandLeftSelect", typeof(ICommand), typeof(HalfMoonSelector), new UIPropertyMetadata(null));
        public static readonly DependencyProperty CommandRightSelectProperty = DependencyProperty.Register("CommandRightSelect", typeof(ICommand), typeof(HalfMoonSelector), new UIPropertyMetadata(null));

        #endregion

        #region Accesseurs Event

        /// <summary>
        /// Affecte ou retourne les handlers pour l'événement LeftSelected
        /// </summary>
        public event RoutedEventHandler LeftSelected
        {
            add
            {
                this.AddHandler(HalfMoonSelector.LeftSelectedEvent, value);
            }
            remove
            {
                this.RemoveHandler(HalfMoonSelector.LeftSelectedEvent, value);
            }
        }

        /// <summary>
        /// Affecte ou retourne les handlers pour l'événement RightSelected
        /// </summary>
        public event RoutedEventHandler RightSelected
        {
            add
            {
                this.AddHandler(HalfMoonSelector.RightSelectedEvent, value);
            }
            remove
            {
                this.RemoveHandler(HalfMoonSelector.RightSelectedEvent, value);
            }
        }

        #endregion

        #region Accesseurs

        /// <summary>
        /// Obtient ou définit si la droitier est sélectionné
        /// </summary>
        public bool IsRigthSelected
        {
            get
            {
                return ((bool)this.GetValue(HalfMoonSelector.IsRigthSelectedProperty));
            }
            set
            {
                this.SetValue(HalfMoonSelector.IsRigthSelectedProperty, value);
            }
        }

        /// <summary>
        /// Obtient ou définit la commande exécuté lorsque gaucher est sélectionnée
        /// </summary>
        public ICommand CommandLeftSelect
        {
            get
            {
                return ((ICommand)this.GetValue(HalfMoonSelector.CommandLeftSelectProperty));
            }
            set
            {
                this.SetValue(HalfMoonSelector.CommandLeftSelectProperty, value);
            }
        }

        /// <summary>
        /// Obtient ou définit la commande exécuté lorsque droitier est sélectionnée
        /// </summary>
        public ICommand CommandRightSelect
        {
            get
            {
                return ((ICommand)this.GetValue(HalfMoonSelector.CommandRightSelectProperty));
            }
            set
            {
                this.SetValue(HalfMoonSelector.CommandRightSelectProperty, value);
            }
        }

        #endregion

        #region Variables d'instances

        private double m_dTravel;

        #endregion

        #region Constructeurs

        /// <summary>
        /// Constructeur statique de la classe
        /// </summary>
        static HalfMoonSelector()
        {
            FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(HalfMoonSelector), new FrameworkPropertyMetadata(typeof(HalfMoonSelector)));
        }

        /// <summary>
        /// Constructeur de la classe
        /// </summary>
        public HalfMoonSelector()
        {
            // Création du scrutteur de manipulation

            this.ManipulationStarting += new System.EventHandler<ManipulationStartingEventArgs>(this.Affine2DManipulationStarting);
            this.ManipulationStarted += new System.EventHandler<ManipulationStartedEventArgs>(this.Affine2DManipulationStarted);
            this.ManipulationDelta += new System.EventHandler<ManipulationDeltaEventArgs>(this.Affine2DManipulationDelta);
        }

        #endregion

        #region Fonctions protégées

        /// <summary>
        /// Se produit sur le changement de la propriété IsRigthSelected
        /// </summary>
        /// <param name="p_bOld">Ancienne valeur</param>
        /// <param name="p_bNew">Nouvelle valeur</param>
        protected virtual void OnIsRigthSelectedChanged(bool p_bOld, bool p_bNew)
        {
            if (p_bNew)
            {
                this.RaiseRightSelected();

                if (this.CommandRightSelect != null)
                    this.CommandRightSelect.Execute(null);
            }
            else if (!p_bNew)
            {
                this.RaiseLeftSelected();

                if (this.CommandLeftSelect != null)
                    this.CommandLeftSelect.Execute(null);
            }
        }

        #endregion

        #region Fontions privées

        /// <summary>
        /// Se produit sur le delta de la manipulation
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void Affine2DManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            this.m_dTravel += e.DeltaManipulation.Translation.X;

            if (this.m_dTravel > 100)
                this.IsRigthSelected = true;
            else if (this.m_dTravel > -100)
                this.IsRigthSelected = false;
        }

        /// <summary>
        /// Se produit sur le début de la manipulation
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void Affine2DManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            this.m_dTravel = 0;
        }

        /// <summary>
        /// Se produit sur l'initialisation de la manipulation
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void Affine2DManipulationStarting(object sender, ManipulationStartingEventArgs e)
        {
            e.ManipulationContainer = this;
            e.Mode = ManipulationModes.TranslateX;
            e.Handled = true;
        }

        /// <summary>
        /// Lance l'événement LeftSelected
        /// </summary>
        private void RaiseLeftSelected()
        {
            RoutedEventArgs oArgs = new RoutedEventArgs(HalfMoonSelector.LeftSelectedEvent);
            this.RaiseEvent(oArgs);
        }

        /// <summary>
        /// Lance l'événement RightSelected
        /// </summary>
        private void RaiseRightSelected()
        {
            RoutedEventArgs oArgs = new RoutedEventArgs(HalfMoonSelector.RightSelectedEvent);
            this.RaiseEvent(oArgs);
        }

        #endregion

        #region Fonctions statiques privées

        /// <summary>
        /// Se produit sur le changement de la propriété IsRigthSelected
        /// </summary>
        /// <param name="p_oItem">Objet de dépendance</param>
        /// <param name="p_oArgs">Argument de l'appel</param>
        private static void OnIsRigthSelectedChanged(DependencyObject p_oItem, DependencyPropertyChangedEventArgs p_oArgs)
        {
            (p_oItem as HalfMoonSelector).OnIsRigthSelectedChanged((bool)p_oArgs.OldValue, (bool)p_oArgs.NewValue);
        }

        #endregion
    }
}
